home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / pyxmpp / jabber / vcard.pyo (.txt) < prev   
Python Compiled Bytecode  |  2008-10-13  |  36KB  |  1,264 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. __revision__ = '$Id: vcard.py 675 2007-06-28 08:36:17Z jajcus $'
  5. __docformat__ = 'restructuredtext en'
  6. import base64
  7. import binascii
  8. import libxml2
  9. import re
  10. import pyxmpp.jid as pyxmpp
  11. from pyxmpp.utils import to_utf8, from_utf8
  12. from pyxmpp.xmlextra import get_node_ns
  13. from pyxmpp.objects import StanzaPayloadObject
  14. from pyxmpp.exceptions import BadRequestProtocolError, JIDMalformedProtocolError, JIDError
  15. VCARD_NS = 'vcard-temp'
  16.  
  17. class Empty(Exception):
  18.     pass
  19.  
  20. valid_string_re = re.compile('^[\\w\\d \\t]*$')
  21. non_quoted_semicolon_re = re.compile('(?<!\\\\);')
  22.  
  23. def quote_semicolon(value):
  24.     return value.replace(';', '\\;')
  25.  
  26.  
  27. def unquote_semicolon(value):
  28.     return value.replace('\\;', ';')
  29.  
  30.  
  31. def rfc2425encode(name, value, parameters = None, charset = 'utf-8'):
  32.     if not parameters:
  33.         parameters = { }
  34.     
  35.     if type(value) is unicode:
  36.         value = value.replace(u'\r\n', u'\\n')
  37.         value = value.replace(u'\n', u'\\n')
  38.         value = value.replace(u'\r', u'\\n')
  39.         value = value.encode(charset, 'replace')
  40.     elif type(value) is not str:
  41.         raise TypeError, 'Bad type for rfc2425 value'
  42.     elif not valid_string_re.match(value):
  43.         parameters['encoding'] = 'b'
  44.         value = binascii.b2a_base64(value)
  45.     
  46.     ret = str(name).lower()
  47.     for k, v in parameters.items():
  48.         ret += ';%s=%s' % (str(k), str(v))
  49.     
  50.     ret += ':'
  51.     while len(value) > 70:
  52.         ret += value[:70] + '\r\n '
  53.         value = value[70:]
  54.     ret += value + '\r\n'
  55.     return ret
  56.  
  57.  
  58. class VCardField:
  59.     
  60.     def __init__(self, name):
  61.         self.name = name
  62.  
  63.     
  64.     def __repr__(self):
  65.         return '<%s %r>' % (self.__class__, self.rfc2426())
  66.  
  67.     
  68.     def rfc2426(self):
  69.         return ''
  70.  
  71.  
  72.  
  73. class VCardString(VCardField):
  74.     
  75.     def __init__(self, name, value, rfc2425parameters = None, empty_ok = False):
  76.         _unused = rfc2425parameters
  77.         VCardField.__init__(self, name)
  78.         if isinstance(value, libxml2.xmlNode):
  79.             value = value.getContent()
  80.             if value:
  81.                 self.value = unicode(value, 'utf-8', 'replace').strip()
  82.             else:
  83.                 self.value = u''
  84.         else:
  85.             self.value = value
  86.         if not (self.value) and not empty_ok:
  87.             raise Empty, 'Empty string value'
  88.         
  89.  
  90.     
  91.     def rfc2426(self):
  92.         return rfc2425encode(self.name, self.value)
  93.  
  94.     
  95.     def as_xml(self, parent):
  96.         return parent.newTextChild(None, to_utf8(self.name.upper()), to_utf8(self.value))
  97.  
  98.     
  99.     def __unicode__(self):
  100.         return self.value
  101.  
  102.     
  103.     def __str__(self):
  104.         return self.value.encode('utf-8')
  105.  
  106.  
  107.  
  108. class VCardXString(VCardString):
  109.     
  110.     def rfc2426(self):
  111.         return rfc2425encode('x-' + self.name, self.value)
  112.  
  113.  
  114.  
  115. class VCardJID(VCardField):
  116.     
  117.     def __init__(self, name, value, rfc2425parameters = None):
  118.         _unused = rfc2425parameters
  119.         VCardField.__init__(self, name)
  120.         if isinstance(value, libxml2.xmlNode):
  121.             
  122.             try:
  123.                 self.value = pyxmpp.jid.JID(value.getContent())
  124.             except JIDError:
  125.                 raise JIDMalformedProtocolError, 'JID malformed'
  126.             except:
  127.                 None<EXCEPTION MATCH>JIDError
  128.             
  129.  
  130.         None<EXCEPTION MATCH>JIDError
  131.         self.value = pyxmpp.jid.JID(value)
  132.         if not self.value:
  133.             raise Empty, 'Empty JID value'
  134.         
  135.  
  136.     
  137.     def rfc2426(self):
  138.         return rfc2425encode('x-jabberid', self.value.as_unicode())
  139.  
  140.     
  141.     def as_xml(self, parent):
  142.         name = to_utf8(self.name.upper())
  143.         content = self.value.as_utf8()
  144.         return parent.newTextChild(None, name, content)
  145.  
  146.     
  147.     def __unicode__(self):
  148.         return self.value.as_unicode()
  149.  
  150.     
  151.     def __str__(self):
  152.         return self.value.as_string()
  153.  
  154.  
  155.  
  156. class VCardName(VCardField):
  157.     
  158.     def __init__(self, name, value, rfc2425parameters = None):
  159.         _unused = rfc2425parameters
  160.         VCardField.__init__(self, name)
  161.         if self.name.upper() != 'N':
  162.             raise RuntimeError, "VCardName handles only 'N' type"
  163.         
  164.         if isinstance(value, libxml2.xmlNode):
  165.             (self.family, self.given, self.middle, self.prefix, self.suffix) = [
  166.                 u''] * 5
  167.             empty = 1
  168.             n = value.children
  169.             vns = get_node_ns(value)
  170.             while n:
  171.                 if n.type != 'element':
  172.                     n = n.next
  173.                     continue
  174.                 
  175.                 ns = get_node_ns(n)
  176.                 if ns and vns and ns.getContent() != vns.getContent():
  177.                     n = n.next
  178.                     continue
  179.                 
  180.                 if n.name == 'FAMILY':
  181.                     self.family = unicode(n.getContent(), 'utf-8')
  182.                     empty = 0
  183.                 
  184.                 if n.name == 'GIVEN':
  185.                     self.given = unicode(n.getContent(), 'utf-8')
  186.                     empty = 0
  187.                 
  188.                 if n.name == 'MIDDLE':
  189.                     self.middle = unicode(n.getContent(), 'utf-8')
  190.                     empty = 0
  191.                 
  192.                 if n.name == 'PREFIX':
  193.                     self.prefix = unicode(n.getContent(), 'utf-8')
  194.                     empty = 0
  195.                 
  196.                 if n.name == 'SUFFIX':
  197.                     self.suffix = unicode(n.getContent(), 'utf-8')
  198.                     empty = 0
  199.                 
  200.                 n = n.next
  201.             if empty:
  202.                 raise Empty, 'Empty N value'
  203.             
  204.         else:
  205.             v = non_quoted_semicolon_re.split(value)
  206.             value = [
  207.                 u''] * 5
  208.             value[:len(v)] = v
  209.             (self.family, self.given, self.middle, self.prefix, self.suffix) = (lambda .0: for val in .0:
  210. unquote_semicolon(val))(value)
  211.  
  212.     
  213.     def rfc2426(self):
  214.         return rfc2425encode('n', u';'.join((lambda .0: for val in .0:
  215. quote_semicolon(val))((self.family, self.given, self.middle, self.prefix, self.suffix))))
  216.  
  217.     
  218.     def as_xml(self, parent):
  219.         n = parent.newChild(None, 'N', None)
  220.         n.newTextChild(None, 'FAMILY', to_utf8(self.family))
  221.         n.newTextChild(None, 'GIVEN', to_utf8(self.given))
  222.         n.newTextChild(None, 'MIDDLE', to_utf8(self.middle))
  223.         n.newTextChild(None, 'PREFIX', to_utf8(self.prefix))
  224.         n.newTextChild(None, 'SUFFIX', to_utf8(self.suffix))
  225.         return n
  226.  
  227.     
  228.     def __unicode__(self):
  229.         r = []
  230.         if self.prefix:
  231.             r.append(self.prefix.replace(u',', u' '))
  232.         
  233.         if self.given:
  234.             r.append(self.given.replace(u',', u' '))
  235.         
  236.         if self.middle:
  237.             r.append(self.middle.replace(u',', u' '))
  238.         
  239.         if self.family:
  240.             r.append(self.family.replace(u',', u' '))
  241.         
  242.         if self.suffix:
  243.             r.append(self.suffix.replace(u',', u' '))
  244.         
  245.         return u' '.join(r)
  246.  
  247.     
  248.     def __str__(self):
  249.         return self.__unicode__().encode('utf-8')
  250.  
  251.  
  252.  
  253. class VCardImage(VCardField):
  254.     
  255.     def __init__(self, name, value, rfc2425parameters = None):
  256.         VCardField.__init__(self, name)
  257.         if not rfc2425parameters:
  258.             rfc2425parameters = { }
  259.         
  260.         (self.uri, self.type, self.image) = [
  261.             None] * 3
  262.         if isinstance(value, libxml2.xmlNode):
  263.             n = value.children
  264.             vns = get_node_ns(value)
  265.             while n:
  266.                 if n.type != 'element':
  267.                     n = n.next
  268.                     continue
  269.                 
  270.                 ns = get_node_ns(n)
  271.                 if ns and vns and ns.getContent() != vns.getContent():
  272.                     n = n.next
  273.                     continue
  274.                 
  275.                 if n.name == 'TYPE':
  276.                     self.type = unicode(n.getContent(), 'utf-8', 'replace')
  277.                 
  278.                 if n.name == 'BINVAL':
  279.                     
  280.                     try:
  281.                         self.image = base64.decodestring(n.getContent())
  282.                     self.image = None
  283.  
  284.                 
  285.                 if n.name == 'EXTVAL':
  286.                     self.uri = unicode(n.getContent(), 'utf-8', 'replace')
  287.                 
  288.                 n = n.next
  289.             if self.uri and self.image:
  290.                 raise ValueError, 'Bad %s value in vcard' % (name,)
  291.             
  292.             if not (self.uri) and not (self.image):
  293.                 raise Empty, 'Bad %s value in vcard' % (name,)
  294.             
  295.         elif rfc2425parameters.get('value', '').lower() == 'uri':
  296.             self.uri = value
  297.             self.type = None
  298.         else:
  299.             self.type = rfc2425parameters.get('type')
  300.             self.image = value
  301.  
  302.     
  303.     def rfc2426(self):
  304.         if self.uri:
  305.             return rfc2425encode(self.name, self.uri, {
  306.                 'value': 'uri' })
  307.         elif self.image:
  308.             if self.type:
  309.                 p = {
  310.                     'type': self.type }
  311.             else:
  312.                 p = { }
  313.             return rfc2425encode(self.name, self.image, p)
  314.         
  315.  
  316.     
  317.     def as_xml(self, parent):
  318.         n = parent.newChild(None, self.name.upper(), None)
  319.         if self.uri:
  320.             n.newTextChild(None, 'EXTVAL', to_utf8(self.uri))
  321.         elif self.type:
  322.             n.newTextChild(None, 'TYPE', self.type)
  323.         
  324.         n.newTextChild(None, 'BINVAL', binascii.b2a_base64(self.image))
  325.         return n
  326.  
  327.     
  328.     def __unicode__(self):
  329.         if self.uri:
  330.             return self.uri
  331.         
  332.         if self.type:
  333.             return u'(%s data)' % (self.type,)
  334.         
  335.         return u'(binary data)'
  336.  
  337.     
  338.     def __str__(self):
  339.         return self.__unicode__().encode('utf-8')
  340.  
  341.  
  342.  
  343. class VCardAdr(VCardField):
  344.     
  345.     def __init__(self, name, value, rfc2425parameters = None):
  346.         VCardField.__init__(self, name)
  347.         if not rfc2425parameters:
  348.             rfc2425parameters = { }
  349.         
  350.         if self.name.upper() != 'ADR':
  351.             raise RuntimeError, "VCardAdr handles only 'ADR' type"
  352.         
  353.         (self.pobox, self.extadr, self.street, self.locality, self.region, self.pcode, self.ctry) = [
  354.             ''] * 7
  355.         self.type = []
  356.         if isinstance(value, libxml2.xmlNode):
  357.             self._VCardAdr__from_xml(value)
  358.         else:
  359.             t = rfc2425parameters.get('type')
  360.             if t:
  361.                 self.type = t.split(',')
  362.             else:
  363.                 self.type = [
  364.                     'intl',
  365.                     'postal',
  366.                     'parcel',
  367.                     'work']
  368.             v = non_quoted_semicolon_re.split(value)
  369.             value = [
  370.                 ''] * 7
  371.             value[:len(v)] = v
  372.             (self.pobox, self.extadr, self.street, self.locality, self.region, self.pcode, self.ctry) = (lambda .0: for val in .0:
  373. unquote_semicolon(val))(value)
  374.  
  375.     
  376.     def __from_xml(self, value):
  377.         n = value.children
  378.         vns = get_node_ns(value)
  379.         while n:
  380.             if n.type != 'element':
  381.                 n = n.next
  382.                 continue
  383.             
  384.             ns = get_node_ns(n)
  385.             if ns and vns and ns.getContent() != vns.getContent():
  386.                 n = n.next
  387.                 continue
  388.             
  389.             if n.name == 'POBOX':
  390.                 self.pobox = unicode(n.getContent(), 'utf-8', 'replace')
  391.             elif n.name in ('EXTADR', 'EXTADD'):
  392.                 self.extadr = unicode(n.getContent(), 'utf-8', 'replace')
  393.             elif n.name == 'STREET':
  394.                 self.street = unicode(n.getContent(), 'utf-8', 'replace')
  395.             elif n.name == 'LOCALITY':
  396.                 self.locality = unicode(n.getContent(), 'utf-8', 'replace')
  397.             elif n.name == 'REGION':
  398.                 self.region = unicode(n.getContent(), 'utf-8', 'replace')
  399.             elif n.name == 'PCODE':
  400.                 self.pcode = unicode(n.getContent(), 'utf-8', 'replace')
  401.             elif n.name == 'CTRY':
  402.                 self.ctry = unicode(n.getContent(), 'utf-8', 'replace')
  403.             elif n.name in ('HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INTL', 'PREF'):
  404.                 self.type.append(n.name.lower())
  405.             
  406.             n = n.next
  407.         if self.type == []:
  408.             self.type = [
  409.                 'intl',
  410.                 'postal',
  411.                 'parcel',
  412.                 'work']
  413.         elif 'dom' in self.type and 'intl' in self.type:
  414.             raise ValueError, "Both 'dom' and 'intl' specified in vcard ADR"
  415.         
  416.  
  417.     
  418.     def rfc2426(self):
  419.         return rfc2425encode('adr', u';'.join((lambda .0: for val in .0:
  420. quote_semicolon(val))((self.pobox, self.extadr, self.street, self.locality, self.region, self.pcode, self.ctry))), {
  421.             'type': ','.join(self.type) })
  422.  
  423.     
  424.     def as_xml(self, parent):
  425.         n = parent.newChild(None, 'ADR', None)
  426.         for t in ('home', 'work', 'postal', 'parcel', 'dom', 'intl', 'pref'):
  427.             if t in self.type:
  428.                 n.newChild(None, t.upper(), None)
  429.                 continue
  430.         
  431.         n.newTextChild(None, 'POBOX', to_utf8(self.pobox))
  432.         n.newTextChild(None, 'EXTADD', to_utf8(self.extadr))
  433.         n.newTextChild(None, 'STREET', to_utf8(self.street))
  434.         n.newTextChild(None, 'LOCALITY', to_utf8(self.locality))
  435.         n.newTextChild(None, 'REGION', to_utf8(self.region))
  436.         n.newTextChild(None, 'PCODE', to_utf8(self.pcode))
  437.         n.newTextChild(None, 'CTRY', to_utf8(self.ctry))
  438.         return n
  439.  
  440.  
  441.  
  442. class VCardLabel(VCardField):
  443.     
  444.     def __init__(self, name, value, rfc2425parameters = None):
  445.         VCardField.__init__(self, name)
  446.         if not rfc2425parameters:
  447.             rfc2425parameters = { }
  448.         
  449.         if self.name.upper() != 'LABEL':
  450.             raise RuntimeError, "VCardAdr handles only 'LABEL' type"
  451.         
  452.         if isinstance(value, libxml2.xmlNode):
  453.             self.lines = []
  454.             self.type = []
  455.             n = value.children
  456.             vns = get_node_ns(value)
  457.             while n:
  458.                 if n.type != 'element':
  459.                     n = n.next
  460.                     continue
  461.                 
  462.                 ns = get_node_ns(n)
  463.                 if ns and vns and ns.getContent() != vns.getContent():
  464.                     n = n.next
  465.                     continue
  466.                 
  467.                 if n.name == 'LINE':
  468.                     l = unicode(n.getContent(), 'utf-8', 'replace').strip()
  469.                     l = l.replace('\n', ' ').replace('\r', ' ')
  470.                     self.lines.append(l)
  471.                 elif n.name in ('HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INTL', 'PREF'):
  472.                     self.type.append(n.name.lower())
  473.                 
  474.                 n = n.next
  475.             if self.type == []:
  476.                 self.type = [
  477.                     'intl',
  478.                     'postal',
  479.                     'parcel',
  480.                     'work']
  481.             elif 'dom' in self.type and 'intl' in self.type:
  482.                 raise ValueError, "Both 'dom' and 'intl' specified in vcard LABEL"
  483.             
  484.             if not self.lines:
  485.                 self.lines = [
  486.                     '']
  487.             
  488.         else:
  489.             t = rfc2425parameters.get('type')
  490.             if t:
  491.                 self.type = t.split(',')
  492.             else:
  493.                 self.type = [
  494.                     'intl',
  495.                     'postal',
  496.                     'parcel',
  497.                     'work']
  498.             self.lines = value.split('\\n')
  499.  
  500.     
  501.     def rfc2426(self):
  502.         return rfc2425encode('label', u'\n'.join(self.lines), {
  503.             'type': ','.join(self.type) })
  504.  
  505.     
  506.     def as_xml(self, parent):
  507.         n = parent.newChild(None, 'ADR', None)
  508.         for t in ('home', 'work', 'postal', 'parcel', 'dom', 'intl', 'pref'):
  509.             if t in self.type:
  510.                 n.newChild(None, t.upper(), None)
  511.                 continue
  512.         
  513.         for l in self.lines:
  514.             n.newTextChild(None, 'LINE', l)
  515.         
  516.         return n
  517.  
  518.  
  519.  
  520. class VCardTel(VCardField):
  521.     
  522.     def __init__(self, name, value, rfc2425parameters = None):
  523.         VCardField.__init__(self, name)
  524.         if not rfc2425parameters:
  525.             rfc2425parameters = { }
  526.         
  527.         if self.name.upper() != 'TEL':
  528.             raise RuntimeError, "VCardTel handles only 'TEL' type"
  529.         
  530.         if isinstance(value, libxml2.xmlNode):
  531.             self.number = None
  532.             self.type = []
  533.             n = value.children
  534.             vns = get_node_ns(value)
  535.             while n:
  536.                 if n.type != 'element':
  537.                     n = n.next
  538.                     continue
  539.                 
  540.                 ns = get_node_ns(n)
  541.                 if ns and vns and ns.getContent() != vns.getContent():
  542.                     n = n.next
  543.                     continue
  544.                 
  545.                 if n.name == 'NUMBER':
  546.                     self.number = unicode(n.getContent(), 'utf-8', 'replace')
  547.                 elif n.name in ('HOME', 'WORK', 'VOICE', 'FAX', 'PAGER', 'MSG', 'CELL', 'VIDEO', 'BBS', 'MODEM', 'ISDN', 'PCS', 'PREF'):
  548.                     self.type.append(n.name.lower())
  549.                 
  550.                 n = n.next
  551.             if self.type == []:
  552.                 self.type = [
  553.                     'voice']
  554.             
  555.             if not self.number:
  556.                 raise Empty, 'No tel number'
  557.             
  558.         else:
  559.             t = rfc2425parameters.get('type')
  560.             if t:
  561.                 self.type = t.split(',')
  562.             else:
  563.                 self.type = [
  564.                     'voice']
  565.             self.number = value
  566.  
  567.     
  568.     def rfc2426(self):
  569.         return rfc2425encode('tel', self.number, {
  570.             'type': ','.join(self.type) })
  571.  
  572.     
  573.     def as_xml(self, parent):
  574.         n = parent.newChild(None, 'TEL', None)
  575.         for t in ('home', 'work', 'voice', 'fax', 'pager', 'msg', 'cell', 'video', 'bbs', 'modem', 'isdn', 'pcs', 'pref'):
  576.             if t in self.type:
  577.                 n.newChild(None, t.upper(), None)
  578.                 continue
  579.         
  580.         n.newTextChild(None, 'NUMBER', to_utf8(self.number))
  581.         return n
  582.  
  583.  
  584.  
  585. class VCardEmail(VCardField):
  586.     
  587.     def __init__(self, name, value, rfc2425parameters = None):
  588.         VCardField.__init__(self, name)
  589.         if not rfc2425parameters:
  590.             rfc2425parameters = { }
  591.         
  592.         if self.name.upper() != 'EMAIL':
  593.             raise RuntimeError, "VCardEmail handles only 'EMAIL' type"
  594.         
  595.         if isinstance(value, libxml2.xmlNode):
  596.             self.address = None
  597.             self.type = []
  598.             n = value.children
  599.             vns = get_node_ns(value)
  600.             while n:
  601.                 if n.type != 'element':
  602.                     n = n.next
  603.                     continue
  604.                 
  605.                 ns = get_node_ns(n)
  606.                 if ns and vns and ns.getContent() != vns.getContent():
  607.                     n = n.next
  608.                     continue
  609.                 
  610.                 if n.name == 'USERID':
  611.                     self.address = unicode(n.getContent(), 'utf-8', 'replace')
  612.                 elif n.name in ('HOME', 'WORK', 'INTERNET', 'X400'):
  613.                     self.type.append(n.name.lower())
  614.                 
  615.                 n = n.next
  616.             if self.type == []:
  617.                 self.type = [
  618.                     'internet']
  619.             
  620.             if not self.address:
  621.                 raise Empty, 'No USERID'
  622.             
  623.         else:
  624.             t = rfc2425parameters.get('type')
  625.             if t:
  626.                 self.type = t.split(',')
  627.             else:
  628.                 self.type = [
  629.                     'internet']
  630.             self.address = value
  631.  
  632.     
  633.     def rfc2426(self):
  634.         return rfc2425encode('email', self.address, {
  635.             'type': ','.join(self.type) })
  636.  
  637.     
  638.     def as_xml(self, parent):
  639.         n = parent.newChild(None, 'EMAIL', None)
  640.         for t in ('home', 'work', 'internet', 'x400'):
  641.             if t in self.type:
  642.                 n.newChild(None, t.upper(), None)
  643.                 continue
  644.         
  645.         n.newTextChild(None, 'USERID', to_utf8(self.address))
  646.         return n
  647.  
  648.  
  649.  
  650. class VCardGeo(VCardField):
  651.     
  652.     def __init__(self, name, value, rfc2425parameters = None):
  653.         _unused = rfc2425parameters
  654.         VCardField.__init__(self, name)
  655.         if self.name.upper() != 'GEO':
  656.             raise RuntimeError, "VCardName handles only 'GEO' type"
  657.         
  658.         if isinstance(value, libxml2.xmlNode):
  659.             (self.lat, self.lon) = [
  660.                 None] * 2
  661.             n = value.children
  662.             vns = get_node_ns(value)
  663.             while n:
  664.                 if n.type != 'element':
  665.                     n = n.next
  666.                     continue
  667.                 
  668.                 ns = get_node_ns(n)
  669.                 if ns and vns and ns.getContent() != vns.getContent():
  670.                     n = n.next
  671.                     continue
  672.                 
  673.                 if n.name == 'LAT':
  674.                     self.lat = unicode(n.getContent(), 'utf-8')
  675.                 
  676.                 if n.name == 'LON':
  677.                     self.lon = unicode(n.getContent(), 'utf-8')
  678.                 
  679.                 n = n.next
  680.             if not (self.lat) or not (self.lon):
  681.                 raise ValueError, 'Bad vcard GEO value'
  682.             
  683.         else:
  684.             (self.lat, self.lon) = (lambda .0: for val in .0:
  685. unquote_semicolon(val))(non_quoted_semicolon_re.split(value))
  686.  
  687.     
  688.     def rfc2426(self):
  689.         return rfc2425encode('geo', u';'.join((lambda .0: for val in .0:
  690. quote_semicolon(val))((self.lat, self.lon))))
  691.  
  692.     
  693.     def as_xml(self, parent):
  694.         n = parent.newChild(None, 'GEO', None)
  695.         n.newTextChild(None, 'LAT', to_utf8(self.lat))
  696.         n.newTextChild(None, 'LON', to_utf8(self.lon))
  697.         return n
  698.  
  699.  
  700.  
  701. class VCardOrg(VCardField):
  702.     
  703.     def __init__(self, name, value, rfc2425parameters = None):
  704.         _unused = rfc2425parameters
  705.         VCardField.__init__(self, name)
  706.         if self.name.upper() != 'ORG':
  707.             raise RuntimeError, "VCardName handles only 'ORG' type"
  708.         
  709.         if isinstance(value, libxml2.xmlNode):
  710.             (self.name, self.unit) = (None, '')
  711.             n = value.children
  712.             vns = get_node_ns(value)
  713.             while n:
  714.                 if n.type != 'element':
  715.                     n = n.next
  716.                     continue
  717.                 
  718.                 ns = get_node_ns(n)
  719.                 if ns and vns and ns.getContent() != vns.getContent():
  720.                     n = n.next
  721.                     continue
  722.                 
  723.                 if n.name == 'ORGNAME':
  724.                     self.name = unicode(n.getContent(), 'utf-8')
  725.                 
  726.                 if n.name == 'ORGUNIT':
  727.                     self.unit = unicode(n.getContent(), 'utf-8')
  728.                 
  729.                 n = n.next
  730.             if not self.name:
  731.                 raise Empty, 'Bad vcard ORG value'
  732.             
  733.         else:
  734.             sp = non_quoted_semicolon_re.split(value, 1)
  735.             if len(sp) > 1:
  736.                 (self.name, self.unit) = (lambda .0: for val in .0:
  737. unquote_semicolon(val))(sp)
  738.             else:
  739.                 self.name = unquote_semicolon(sp[0])
  740.                 self.unit = None
  741.  
  742.     
  743.     def rfc2426(self):
  744.         if self.unit:
  745.             return rfc2425encode('org', u';'.join((lambda .0: for val in .0:
  746. quote_semicolon(val))((self.name, self.unit))))
  747.         else:
  748.             return rfc2425encode('org', unicode(quote_semicolon(self.name)))
  749.  
  750.     
  751.     def as_xml(self, parent):
  752.         n = parent.newChild(None, 'ORG', None)
  753.         n.newTextChild(None, 'ORGNAME', to_utf8(self.name))
  754.         n.newTextChild(None, 'ORGUNIT', to_utf8(self.unit))
  755.         return n
  756.  
  757.  
  758.  
  759. class VCardCategories(VCardField):
  760.     
  761.     def __init__(self, name, value, rfc2425parameters = None):
  762.         _unused = rfc2425parameters
  763.         VCardField.__init__(self, name)
  764.         self.name = name
  765.         if self.name.upper() != 'CATEGORIES':
  766.             raise RuntimeError, "VCardName handles only 'CATEGORIES' type"
  767.         
  768.         if isinstance(value, libxml2.xmlNode):
  769.             self.keywords = []
  770.             n = value.children
  771.             vns = get_node_ns(value)
  772.             while n:
  773.                 if n.type != 'element':
  774.                     n = n.next
  775.                     continue
  776.                 
  777.                 ns = get_node_ns(n)
  778.                 if ns and vns and ns.getContent() != vns.getContent():
  779.                     n = n.next
  780.                     continue
  781.                 
  782.                 if n.name == 'KEYWORD':
  783.                     self.keywords.append(unicode(n.getContent(), 'utf-8'))
  784.                 
  785.                 n = n.next
  786.             if not self.keywords:
  787.                 raise Empty, 'Bad vcard CATEGORIES value'
  788.             
  789.         else:
  790.             self.keywords = value.split(',')
  791.  
  792.     
  793.     def rfc2426(self):
  794.         return rfc2425encode('keywords', u','.join(self.keywords))
  795.  
  796.     
  797.     def as_xml(self, parent):
  798.         n = parent.newChild(None, 'CATEGORIES', None)
  799.         for k in self.keywords:
  800.             n.newTextChild(None, 'KEYWORD', to_utf8(k))
  801.         
  802.         return n
  803.  
  804.  
  805.  
  806. class VCardSound(VCardField):
  807.     
  808.     def __init__(self, name, value, rfc2425parameters = None):
  809.         VCardField.__init__(self, name)
  810.         if not rfc2425parameters:
  811.             rfc2425parameters = { }
  812.         
  813.         (self.uri, self.sound, self.phonetic) = [
  814.             None] * 3
  815.         if isinstance(value, libxml2.xmlNode):
  816.             n = value.children
  817.             vns = get_node_ns(value)
  818.             while n:
  819.                 if n.type != 'element':
  820.                     n = n.next
  821.                     continue
  822.                 
  823.                 ns = get_node_ns(n)
  824.                 if ns and vns and ns.getContent() != vns.getContent():
  825.                     n = n.next
  826.                     continue
  827.                 
  828.                 if n.name == 'BINVAL':
  829.                     if self.phonetic or self.uri:
  830.                         raise ValueError, 'Bad SOUND value in vcard'
  831.                     
  832.                     self.sound = base64.decodestring(n.getContent())
  833.                 
  834.                 if n.name == 'PHONETIC':
  835.                     if self.sound or self.uri:
  836.                         raise ValueError, 'Bad SOUND value in vcard'
  837.                     
  838.                     self.phonetic = unicode(n.getContent(), 'utf-8', 'replace')
  839.                 
  840.                 if n.name == 'EXTVAL':
  841.                     if self.phonetic or self.sound:
  842.                         raise ValueError, 'Bad SOUND value in vcard'
  843.                     
  844.                     self.uri = unicode(n.getContent(), 'utf-8', 'replace')
  845.                 
  846.                 n = n.next
  847.             if not (self.phonetic) and not (self.uri) and not (self.sound):
  848.                 raise Empty, 'Bad SOUND value in vcard'
  849.             
  850.         elif rfc2425parameters.get('value', '').lower() == 'uri':
  851.             self.uri = value
  852.             self.sound = None
  853.             self.phonetic = None
  854.         else:
  855.             self.sound = value
  856.             self.uri = None
  857.             self.phonetic = None
  858.  
  859.     
  860.     def rfc2426(self):
  861.         if self.uri:
  862.             return rfc2425encode(self.name, self.uri, {
  863.                 'value': 'uri' })
  864.         elif self.sound:
  865.             return rfc2425encode(self.name, self.sound)
  866.         
  867.  
  868.     
  869.     def as_xml(self, parent):
  870.         n = parent.newChild(None, self.name.upper(), None)
  871.         if self.uri:
  872.             n.newTextChild(None, 'EXTVAL', to_utf8(self.uri))
  873.         elif self.phonetic:
  874.             n.newTextChild(None, 'PHONETIC', to_utf8(self.phonetic))
  875.         else:
  876.             n.newTextChild(None, 'BINVAL', binascii.b2a_base64(self.sound))
  877.         return n
  878.  
  879.  
  880.  
  881. class VCardPrivacy(VCardField):
  882.     
  883.     def __init__(self, name, value, rfc2425parameters = None):
  884.         _unused = rfc2425parameters
  885.         VCardField.__init__(self, name)
  886.         if isinstance(value, libxml2.xmlNode):
  887.             self.value = None
  888.             n = value.children
  889.             vns = get_node_ns(value)
  890.             while n:
  891.                 if n.type != 'element':
  892.                     n = n.next
  893.                     continue
  894.                 
  895.                 ns = get_node_ns(n)
  896.                 if ns and vns and ns.getContent() != vns.getContent():
  897.                     n = n.next
  898.                     continue
  899.                 
  900.                 if n.name == 'PUBLIC':
  901.                     self.value = 'public'
  902.                 elif n.name == 'PRIVATE':
  903.                     self.value = 'private'
  904.                 elif n.name == 'CONFIDENTAL':
  905.                     self.value = 'confidental'
  906.                 
  907.                 n = n.next
  908.             if not self.value:
  909.                 raise Empty
  910.             
  911.         else:
  912.             self.value = value
  913.  
  914.     
  915.     def rfc2426(self):
  916.         return rfc2425encode(self.name, self.value)
  917.  
  918.     
  919.     def as_xml(self, parent):
  920.         if self.value in ('public', 'private', 'confidental'):
  921.             n = parent.newChild(None, self.name.upper(), None)
  922.             n.newChild(None, self.value.upper(), None)
  923.             return n
  924.         
  925.  
  926.  
  927.  
  928. class VCardKey(VCardField):
  929.     
  930.     def __init__(self, name, value, rfc2425parameters = None):
  931.         VCardField.__init__(self, name)
  932.         if not rfc2425parameters:
  933.             rfc2425parameters = { }
  934.         
  935.         if isinstance(value, libxml2.xmlNode):
  936.             (self.type, self.cred) = (None, None)
  937.             n = value.children
  938.             vns = get_node_ns(value)
  939.             while n:
  940.                 if n.type != 'element':
  941.                     n = n.next
  942.                     continue
  943.                 
  944.                 ns = get_node_ns(n)
  945.                 if ns and vns and ns.getContent() != vns.getContent():
  946.                     n = n.next
  947.                     continue
  948.                 
  949.                 if n.name == 'TYPE':
  950.                     self.type = unicode(n.getContent(), 'utf-8', 'replace')
  951.                 
  952.                 if n.name == 'CRED':
  953.                     self.cred = base64.decodestring(n.getContent())
  954.                 
  955.                 n = n.next
  956.             if not self.cred:
  957.                 raise Empty, 'Bad %s value in vcard' % (name,)
  958.             
  959.         else:
  960.             self.type = rfc2425parameters.get('type')
  961.             self.cred = value
  962.  
  963.     
  964.     def rfc2426(self):
  965.         if self.type:
  966.             p = {
  967.                 'type': self.type }
  968.         else:
  969.             p = { }
  970.         return rfc2425encode(self.name, self.cred, p)
  971.  
  972.     
  973.     def as_xml(self, parent):
  974.         n = parent.newChild(None, self.name.upper(), None)
  975.         if self.type:
  976.             n.newTextChild(None, 'TYPE', self.type)
  977.         
  978.         n.newTextChild(None, 'CRED', binascii.b2a_base64(self.cred))
  979.         return n
  980.  
  981.  
  982.  
  983. class VCard(StanzaPayloadObject):
  984.     xml_element_name = 'vCard'
  985.     xml_element_namespace = VCARD_NS
  986.     components = {
  987.         'FN': (VCardString, 'required'),
  988.         'N': (VCardName, 'required'),
  989.         'NICKNAME': (VCardString, 'multi'),
  990.         'PHOTO': (VCardImage, 'multi'),
  991.         'BDAY': (VCardString, 'multi'),
  992.         'ADR': (VCardAdr, 'multi'),
  993.         'LABEL': (VCardLabel, 'multi'),
  994.         'TEL': (VCardTel, 'multi'),
  995.         'EMAIL': (VCardEmail, 'multi'),
  996.         'JABBERID': (VCardJID, 'multi'),
  997.         'MAILER': (VCardString, 'multi'),
  998.         'TZ': (VCardString, 'multi'),
  999.         'GEO': (VCardGeo, 'multi'),
  1000.         'TITLE': (VCardString, 'multi'),
  1001.         'ROLE': (VCardString, 'multi'),
  1002.         'LOGO': (VCardImage, 'multi'),
  1003.         'AGENT': ('VCardAgent', 'ignore'),
  1004.         'ORG': (VCardOrg, 'multi'),
  1005.         'CATEGORIES': (VCardCategories, 'multi'),
  1006.         'NOTE': (VCardString, 'multi'),
  1007.         'PRODID': (VCardString, 'multi'),
  1008.         'REV': (VCardString, 'multi'),
  1009.         'SORT-STRING': (VCardString, 'multi'),
  1010.         'SOUND': (VCardSound, 'multi'),
  1011.         'UID': (VCardString, 'multi'),
  1012.         'URL': (VCardString, 'multi'),
  1013.         'CLASS': (VCardString, 'multi'),
  1014.         'KEY': (VCardKey, 'multi'),
  1015.         'DESC': (VCardXString, 'multi') }
  1016.     
  1017.     def __init__(self, data):
  1018.         self.n = None
  1019.         del self.n
  1020.         self.content = { }
  1021.         if isinstance(data, libxml2.xmlNode):
  1022.             self._VCard__from_xml(data)
  1023.         else:
  1024.             self._VCard__from_rfc2426(data)
  1025.         if not self.content.get('N') and self.content.get('FN'):
  1026.             s = self.content['FN'].value.replace(';', ',')
  1027.             s = s.split(None, 2)
  1028.             if len(s) == 2:
  1029.                 s = u'%s;%s;;;' % (s[1], s[0])
  1030.             elif len(s) == 3:
  1031.                 s = u'%s;%s;%s' % (s[2], s[0], s[1])
  1032.             else:
  1033.                 s = u'%s;;;;' % (s[0],)
  1034.             self.content['N'] = VCardName('N', s)
  1035.         elif not self.content.get('FN') and self.content.get('N'):
  1036.             self._VCard__make_fn()
  1037.         
  1038.         for _unused, tp in self.components.items():
  1039.             if self.content.has_key(c):
  1040.                 continue
  1041.             
  1042.             if tp == 'required':
  1043.                 raise ValueError, '%s is missing' % (c,)
  1044.                 continue
  1045.             if tp == 'multi':
  1046.                 self.content[c] = []
  1047.                 continue
  1048.             if tp == 'optional':
  1049.                 self.content[c] = None
  1050.                 continue
  1051.             continue
  1052.         
  1053.  
  1054.     
  1055.     def __make_fn(self):
  1056.         s = []
  1057.         if self.n.prefix:
  1058.             s.append(self.n.prefix)
  1059.         
  1060.         if self.n.given:
  1061.             s.append(self.n.given)
  1062.         
  1063.         if self.n.middle:
  1064.             s.append(self.n.middle)
  1065.         
  1066.         if self.n.family:
  1067.             s.append(self.n.family)
  1068.         
  1069.         if self.n.suffix:
  1070.             s.append(self.n.suffix)
  1071.         
  1072.         s = u' '.join(s)
  1073.         self.content['FN'] = VCardString('FN', s, empty_ok = True)
  1074.  
  1075.     
  1076.     def __from_xml(self, data):
  1077.         ns = get_node_ns(data)
  1078.         if ns and ns.getContent() != VCARD_NS:
  1079.             raise ValueError, 'Not in the %r namespace' % (VCARD_NS,)
  1080.         
  1081.         if data.name.lower() != 'vCard'.lower():
  1082.             raise ValueError, 'Bad root element name: %r' % (data.name,)
  1083.         
  1084.         n = data.children
  1085.         dns = get_node_ns(data)
  1086.         while n:
  1087.             if n.type != 'element':
  1088.                 n = n.next
  1089.                 continue
  1090.             
  1091.             ns = get_node_ns(n)
  1092.             if ns and dns and ns.getContent() != dns.getContent():
  1093.                 n = n.next
  1094.                 continue
  1095.             
  1096.             if not self.components.has_key(n.name):
  1097.                 n = n.next
  1098.                 continue
  1099.             
  1100.             (cl, tp) = self.components[n.name]
  1101.             if tp in ('required', 'optional'):
  1102.                 if self.content.has_key(n.name):
  1103.                     raise ValueError, 'Duplicate %s' % (n.name,)
  1104.                 
  1105.                 
  1106.                 try:
  1107.                     self.content[n.name] = cl(n.name, n)
  1108.                 except Empty:
  1109.                     pass
  1110.                 except:
  1111.                     None<EXCEPTION MATCH>Empty
  1112.                 
  1113.  
  1114.             None<EXCEPTION MATCH>Empty
  1115.             if tp == 'multi':
  1116.                 if not self.content.has_key(n.name):
  1117.                     self.content[n.name] = []
  1118.                 
  1119.                 
  1120.                 try:
  1121.                     self.content[n.name].append(cl(n.name, n))
  1122.                 except Empty:
  1123.                     pass
  1124.                 except:
  1125.                     None<EXCEPTION MATCH>Empty
  1126.                 
  1127.  
  1128.             None<EXCEPTION MATCH>Empty
  1129.             n = n.next
  1130.  
  1131.     
  1132.     def __from_rfc2426(self, data):
  1133.         data = from_utf8(data)
  1134.         lines = data.split('\n')
  1135.         started = 0
  1136.         current = None
  1137.         for l in lines:
  1138.             if not l:
  1139.                 continue
  1140.             
  1141.             if l[-1] == '\r':
  1142.                 l = l[:-1]
  1143.             
  1144.             if not l:
  1145.                 continue
  1146.             
  1147.             if l[0] in ' \t':
  1148.                 if current is None:
  1149.                     continue
  1150.                 
  1151.                 current += l[1:]
  1152.                 continue
  1153.             
  1154.             if not started and current and current.upper().strip() == 'BEGIN:VCARD':
  1155.                 started = 1
  1156.             elif started and current.upper().strip() == 'END:VCARD':
  1157.                 current = None
  1158.                 break
  1159.             elif current and started:
  1160.                 self._process_rfc2425_record(current)
  1161.             
  1162.             current = l
  1163.         
  1164.         if started and current:
  1165.             self._process_rfc2425_record(current)
  1166.         
  1167.  
  1168.     
  1169.     def _process_rfc2425_record(self, data):
  1170.         (label, value) = data.split(':', 1)
  1171.         value = value.replace('\\n', '\n').replace('\\N', '\n')
  1172.         psplit = label.lower().split(';')
  1173.         name = psplit[0]
  1174.         params = psplit[1:]
  1175.         if u'.' in name:
  1176.             name = name.split('.', 1)[1]
  1177.         
  1178.         name = name.upper()
  1179.         if name in (u'X-DESC', u'X-JABBERID'):
  1180.             name = name[2:]
  1181.         
  1182.         if not self.components.has_key(name):
  1183.             return None
  1184.         
  1185.         (cl, tp) = self.components[name]
  1186.         if tp in ('required', 'optional'):
  1187.             if self.content.has_key(name):
  1188.                 raise ValueError, 'Duplicate %s' % (name,)
  1189.             
  1190.             
  1191.             try:
  1192.                 self.content[name] = cl(name, value, params)
  1193.             except Empty:
  1194.                 pass
  1195.             except:
  1196.                 None<EXCEPTION MATCH>Empty
  1197.             
  1198.  
  1199.         None<EXCEPTION MATCH>Empty
  1200.         if tp == 'multi':
  1201.             if not self.content.has_key(name):
  1202.                 self.content[name] = []
  1203.             
  1204.             
  1205.             try:
  1206.                 self.content[name].append(cl(name, value, params))
  1207.             except Empty:
  1208.                 pass
  1209.             except:
  1210.                 None<EXCEPTION MATCH>Empty
  1211.             
  1212.  
  1213.         None<EXCEPTION MATCH>Empty
  1214.         return None
  1215.  
  1216.     
  1217.     def __repr__(self):
  1218.         return '<vCard of %r>' % (self.content['FN'].value,)
  1219.  
  1220.     
  1221.     def rfc2426(self):
  1222.         ret = 'begin:VCARD\r\n'
  1223.         ret += 'version:3.0\r\n'
  1224.         for _unused, value in self.content.items():
  1225.             if value is None:
  1226.                 continue
  1227.             
  1228.             if type(value) is list:
  1229.                 for v in value:
  1230.                     ret += v.rfc2426()
  1231.                 
  1232.             v = value.rfc2426()
  1233.             ret += v
  1234.         
  1235.         return ret + 'end:VCARD\r\n'
  1236.  
  1237.     
  1238.     def complete_xml_element(self, xmlnode, _unused):
  1239.         for _unused1, value in self.content.items():
  1240.             if value is None:
  1241.                 continue
  1242.             
  1243.             if type(value) is list:
  1244.                 for v in value:
  1245.                     v.as_xml(xmlnode)
  1246.                 
  1247.             value.as_xml(xmlnode)
  1248.         
  1249.  
  1250.     
  1251.     def __getattr__(self, name):
  1252.         
  1253.         try:
  1254.             return self.content[name.upper().replace('_', '-')]
  1255.         except KeyError:
  1256.             raise AttributeError, 'Attribute %r not found' % (name,)
  1257.  
  1258.  
  1259.     
  1260.     def __getitem__(self, name):
  1261.         return self.content[name.upper()]
  1262.  
  1263.  
  1264.